home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / comm / tcp / netinput37_3.lha / NetInput / source / netinput.c < prev    next >
C/C++ Source or Header  |  1995-07-24  |  12KB  |  464 lines

  1. /*
  2. ** $VER: netinput.c 1.3 (22 Jul 1995)
  3. **
  4. ** AMIGA netinput client code
  5. **
  6. ** (C (14 Jul 1995) Copyright 1995 Marius Gröger
  7. **     All Rights Reserved
  8. **
  9. ** $HISTORY:
  10. **
  11. ** 22 Jul 1995 : 001.003 :  QUIET option
  12. ** 14 Jul 1995 : 001.002 :  some code cleanup
  13. ** 06 Mar 1995 : 001.001 :  version id added
  14. ** 05 Mar 1995 : 001.000 :  created
  15. */
  16.  
  17. #define DEBUG 0
  18.  
  19. /*F*/ /* includes */
  20. #include <NETINCLUDE:sys/types.h>
  21. #include <NETINCLUDE:sys/stat.h>
  22. #include <NETINCLUDE:stdio.h>
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <errno.h>
  27. #include <string.h>
  28. #include <clib/netlib_protos.h>
  29. #include <netdb.h>
  30.  
  31. #include <clib/dos_protos.h>
  32. #include <pragmas/dos_pragmas.h>
  33.  
  34. #include <clib/exec_protos.h>
  35. #include <pragmas/exec_sysbase_pragmas.h>
  36.  
  37. #include <exec/memory.h>
  38. #include <exec/io.h>
  39. #include <exec/interrupts.h>
  40.  
  41. #include <devices/input.h>
  42. #include <devices/inputevent.h>
  43.  
  44. #include "netinput.h"
  45. #include "unixsem.h"
  46. #include "compiler.h"
  47. #include "debug.h"
  48.  
  49. /*E*/
  50. /*F*/ /* global data */
  51. extern struct Library *SocketBase, *DOSBase;
  52.  
  53. #define TEMPLATE "HOST/A,IMM=IGNOREMOUSEMOVES/K/N,QUIET/S"
  54. enum { ARG_HOST, ARG_IMM, ARG_QUIET, ARG_COUNT };
  55.  
  56. #define MAX_IMM 900000
  57. #define MIN_IMM 0
  58. #define DEF_IMM 0
  59.  
  60.    /*
  61.    ** we maintain an InputEvent-FIFO of FIFO_COUNT elements
  62.    ** this value MUST be power of 2!
  63.    */
  64. #define FIFO_COUNT 64
  65.  
  66. typedef struct GlobalData
  67. {
  68.    struct Library   *gd_SysBase,
  69.                     *gd_UtilityBase,
  70.                     *gd_DOSBase;
  71.    struct MsgPort   *gd_IPort;
  72.    struct IOStdReq  *gd_IReq;
  73.    struct Interrupt  gd_InputHandler;
  74.    UBYTE             gd_ProgramName[100];
  75.    UBYTE             gd_HostName[64];
  76.    ULONG             gd_Flags;
  77.    int               gd_Socket;
  78.    CountSemaphore    gd_Full,
  79.                      gd_Empty;
  80.    struct InputEvent gd_Event[FIFO_COUNT],
  81.                      gd_Intermediate;
  82.    UWORD             gd_Write, gd_Read;
  83.    struct Task      *gd_We;
  84.    LONG              gd_IgnoreMouseMoves;
  85.    int               gd_Quiet : 1;
  86. } *GD;
  87.  
  88. #define FOGF_HANDLER_INSTALLED   (1<<0)
  89.  
  90. #ifdef __SASC
  91.      /*
  92.      ** redirect all shared library bases to our device base.
  93.      */
  94. #  define SysBase      gd->gd_SysBase
  95. #  define DOSBase      gd->gd_DOSBase
  96. #  define UtilityBase  gd->gd_UtilityBase
  97.      /*
  98.      ** This macro declares a local variable which temporary gets
  99.      ** SysBase directly from AbsExecBase.
  100.      */
  101. #  define LOCALSYSBASE struct { void *gd_SysBase; } *gd = (void*)0x4
  102. #else
  103. #  error Please define library bases for your compiler
  104. #endif
  105.  
  106.  
  107. /*E*/
  108.  
  109. /*F*/ /* revision */
  110. #define VERSION 37
  111. #define REVISION 1
  112. #define DATE "22.07.95"
  113. #define VERS "netinputd 37.1"
  114. #define VSTRING "netinputd 37.1 (22.07.95)"
  115. #define VERSTAG "\0$VER: netinputd 37.1 (22.07.95)"
  116. const STATIC UBYTE version[]=VERSTAG;
  117. /*E*/
  118.  
  119. /*F*/ /* private symbols */
  120. static int init_client(char *hostname, char *servername, char *protocolname, char *yourname);
  121. static BOOL parseargs(GD gd);
  122. static VOID freeall(GD gd);
  123. static BOOL openall(GD gd);
  124. static GD creategd(VOID);
  125. static BOOL request(GD gd, ULONG type, ULONG flags);
  126. static ASM SAVEDS struct InputEvent *inputhandler(REG(a0) struct InputEvent *event, REG(a1) GD gd);
  127. static VOID removehandler(GD gd);
  128. static BOOL installhandler(GD gd);
  129. /*E*/
  130. /*F*/ /* exported symbols */
  131. extern VOID main(VOID);
  132. /*E*/
  133.  
  134. /*F*/ static int init_client(char *hostname, char *servername, char *protocolname, char *yourname)
  135. {
  136.    int sock = -1;
  137.    struct servent *sp;
  138.    struct hostent *hp;
  139.    struct sockaddr_in server;
  140.  
  141.    sp = getservbyname(servername, protocolname);
  142.    if (sp != NULL)
  143.    {
  144.       hp = gethostbyname(hostname);
  145.       if (hp != NULL)
  146.       {
  147.          bzero((char *)&server, sizeof(server));
  148.          server.sin_port = sp->s_port;
  149.          bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
  150.          server.sin_family = hp->h_addrtype;
  151.  
  152.          sock = socket(AF_INET, (LONG)(strcmp(protocolname,"tcp") ? SOCK_DGRAM : SOCK_STREAM), 0);
  153.          if (sock >= 0)
  154.          {
  155.             if (connect((LONG)sock, (struct sockaddr *)&server, sizeof (server)) < 0)
  156.             {
  157.                close(sock);
  158.                sock = -1;
  159.             }
  160.          }
  161.       }
  162.    }
  163.  
  164.    return sock;
  165. }
  166. /*E*/
  167.  
  168. /*F*/ static BOOL parseargs(GD gd)
  169. {
  170.    struct RDArgs *rda;
  171.    BOOL rc = FALSE;
  172.    LONG param[ARG_COUNT];
  173.  
  174.    memset(param, 0, sizeof(param));
  175.  
  176.    if (rda = ReadArgs(TEMPLATE, param, NULL))
  177.    {
  178.       strncpy(gd->gd_HostName, (char*)param[ARG_HOST], sizeof(gd->gd_HostName)-1);
  179.  
  180.       gd->gd_IgnoreMouseMoves = DEF_IMM;
  181.       if (param[ARG_IMM])
  182.       {
  183.          gd->gd_IgnoreMouseMoves = *((LONG*)param[ARG_IMM]);
  184.          if (gd->gd_IgnoreMouseMoves > MAX_IMM) gd->gd_IgnoreMouseMoves = MAX_IMM;
  185.          else if (gd->gd_IgnoreMouseMoves < MIN_IMM) gd->gd_IgnoreMouseMoves = MIN_IMM;
  186.       }
  187.  
  188.       d(("hostname %s, imm %ld\n",gd->gd_HostName, gd->gd_IgnoreMouseMoves));
  189.  
  190.       gd->gd_Quiet = (param[ARG_QUIET] != 0);
  191.  
  192.       rc = TRUE;
  193.  
  194.       FreeArgs(rda);
  195.    }
  196.    else PrintFault(IoErr(), gd->gd_ProgramName);
  197.  
  198.    return(rc);
  199. }
  200. /*E*/
  201.  
  202. /*F*/ static VOID removehandler(GD gd)
  203. {
  204.    if (gd->gd_Flags & FOGF_HANDLER_INSTALLED)
  205.    {
  206.       gd->gd_IReq->io_Command = IND_REMHANDLER;
  207.       gd->gd_IReq->io_Data = (APTR)&gd->gd_InputHandler;
  208.       gd->gd_IReq->io_Length = sizeof(struct Interrupt);
  209.       if (!DoIO((struct IORequest*)gd->gd_IReq))
  210.          gd->gd_Flags &= ~FOGF_HANDLER_INSTALLED;
  211.    }
  212. }
  213. /*E*/
  214. /*F*/ static BOOL installhandler(GD gd)
  215. {
  216.    BOOL rv = FALSE;
  217.  
  218.    gd->gd_InputHandler.is_Code = (void (*)())&inputhandler;
  219.    gd->gd_InputHandler.is_Data = (APTR)gd;
  220.    gd->gd_InputHandler.is_Node.ln_Pri = 127;
  221.    gd->gd_InputHandler.is_Node.ln_Type = NT_UNKNOWN;
  222.    gd->gd_InputHandler.is_Node.ln_Name = "« netinput »";
  223.    gd->gd_IReq->io_Command = IND_ADDHANDLER;
  224.    gd->gd_IReq->io_Data = (APTR)&gd->gd_InputHandler;
  225.    gd->gd_IReq->io_Length = sizeof(struct Interrupt);
  226.    if (!DoIO((struct IORequest*)gd->gd_IReq))
  227.    {
  228.       gd->gd_Flags |= FOGF_HANDLER_INSTALLED;
  229.       rv = TRUE;
  230.    }
  231.  
  232.    return rv;
  233. }
  234. /*E*/
  235.  
  236. /*F*/ static VOID freeall(GD gd)
  237. {
  238.    if (gd->gd_IReq)
  239.    {
  240.       if (gd->gd_IReq->io_Device) CloseDevice((struct IORequest*)gd->gd_IReq);
  241.       DeleteIORequest(gd->gd_IReq);
  242.    }
  243.    if (gd->gd_IPort) DeleteMsgPort(gd->gd_IPort);
  244.    if (DOSBase) CloseLibrary(DOSBase);
  245.    if (UtilityBase) CloseLibrary(UtilityBase);
  246.    FreeVec(gd);
  247. }
  248. /*E*/
  249. /*F*/ static BOOL openall(GD gd)
  250. {
  251.    BOOL rv = FALSE;
  252.  
  253.    sinit(&gd->gd_Full,-1);
  254.    sinit(&gd->gd_Empty,-1);
  255.  
  256.    sset(&gd->gd_Full, 0);
  257.    sset(&gd->gd_Empty, FIFO_COUNT);
  258.  
  259.    gd->gd_Read = 0;
  260.    gd->gd_Write = 0;
  261.  
  262.    gd->gd_We = FindTask(NULL);
  263.  
  264.    d(("opening dos.library\n"))
  265.    if (DOSBase = OpenLibrary("dos.library", 37))
  266.    {
  267.       d(("opening utility.library\n"))
  268.       if (UtilityBase = OpenLibrary("utility.library", 37))
  269.       {
  270.          d(("creating msg port\n"))
  271.          if (gd->gd_IPort = CreateMsgPort())
  272.          {
  273.             d(("creating io request\n"))
  274.             if (gd->gd_IReq = CreateIORequest(gd->gd_IPort, sizeof(struct IOStdReq)))
  275.             {
  276.                d(("opening input.device\n"))
  277.                if (!OpenDevice("input.device",0,(struct IORequest*)gd->gd_IReq, 0))
  278.                {
  279.                   rv = TRUE;
  280.                }
  281.             }
  282.          }
  283.       }
  284.    }
  285.  
  286.    return rv;
  287. }
  288. /*E*/
  289. /*F*/ static GD creategd(VOID)
  290. {
  291.    GD new;
  292.    LOCALSYSBASE;
  293.  
  294.    new = AllocVec(sizeof(struct GlobalData), MEMF_ANY | MEMF_CLEAR);
  295.    new->gd_SysBase = SysBase;
  296.  
  297.    return new;
  298. }
  299. /*E*/
  300.  
  301. /*F*/ static VOID INLINE forwardevent(GD gd, struct InputEvent *event)
  302. {
  303.    swait(&gd->gd_Empty);
  304.    gd->gd_Event[gd->gd_Write] = *event;
  305.    ssignal(&gd->gd_Full);
  306.  
  307.    gd->gd_Write = (gd->gd_Write+1) & (FIFO_COUNT-1);
  308. }
  309. /*E*/
  310. /*F*/ static ASM SAVEDS struct InputEvent *inputhandler(REG(a0) struct InputEvent *event, REG(a1) GD gd)
  311. {
  312.    switch(event->ie_Class)
  313.    {
  314.       case IECLASS_RAWMOUSE:
  315.          if ((event->ie_Code & 0xFF) != IECODE_NOBUTTON)
  316.          {
  317.             if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
  318.             {
  319.                d(("writing event 3\n"));
  320.                forwardevent(gd, &gd->gd_Intermediate);
  321.                gd->gd_Intermediate.ie_Class = IECLASS_NULL;
  322.             }
  323.             forwardevent(gd, event);
  324.          }
  325.          else if (gd->gd_IgnoreMouseMoves)
  326.          {
  327.             if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
  328.             {
  329.                d (("%ld/%ld - %ld/%ld\n",event->ie_TimeStamp.tv_secs,
  330.                                          event->ie_TimeStamp.tv_micro,
  331.                                          gd->gd_Intermediate.ie_TimeStamp.tv_secs,
  332.                                          gd->gd_Intermediate.ie_TimeStamp.tv_micro));
  333.  
  334.                if ((event->ie_TimeStamp.tv_secs == gd->gd_Intermediate.ie_TimeStamp.tv_secs) &&
  335.                    ((event->ie_TimeStamp.tv_micro - gd->gd_Intermediate.ie_TimeStamp.tv_micro) <= gd->gd_IgnoreMouseMoves))
  336.                {
  337.                   d(("storing event 1\n"));
  338.                   gd->gd_Intermediate = *event;
  339.                }
  340.                else
  341.                {
  342.                   d(("writing event 1\n"));
  343.                   gd->gd_Intermediate.ie_Class = IECLASS_NULL;
  344.                   forwardevent(gd, event);
  345.                }
  346.             }
  347.             else
  348.             {
  349.                d(("storing event 2\n"));
  350.                gd->gd_Intermediate = *event;
  351.             }
  352.          }
  353.          else
  354.          {
  355.             d(("writing event 2\n"));
  356.             forwardevent(gd, event);
  357.          }
  358.          event = NULL;
  359.       break;
  360.  
  361.       case IECLASS_RAWKEY:
  362.          if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
  363.          {
  364.             forwardevent(gd, &gd->gd_Intermediate);
  365.             gd->gd_Intermediate.ie_Class = IECLASS_NULL;
  366.          }
  367.          if (((event->ie_Code & ~IECODE_UP_PREFIX) == 0x45) && (event->ie_Qualifier & IEQUALIFIER_CONTROL))
  368.          {
  369.             if (event->ie_Code & IECODE_UP_PREFIX)
  370.                Signal(gd->gd_We, SIGBREAKF_CTRL_C);
  371.  
  372.             event = NULL;
  373.             break;
  374.          }
  375.          forwardevent(gd,event);
  376.          event = NULL;
  377.       break;
  378.  
  379.       default:
  380.          if (gd->gd_Intermediate.ie_Class != IECLASS_NULL)
  381.          {
  382.             forwardevent(gd, &gd->gd_Intermediate);
  383.             gd->gd_Intermediate.ie_Class = IECLASS_NULL;
  384.          }
  385.       break;
  386.    }
  387.    return event;
  388. }
  389. /*E*/
  390.  
  391. /*F*/ static BOOL request(GD gd, ULONG type, ULONG flags)
  392. {
  393.    int l;
  394.    struct foPacket foc;
  395.  
  396.    foc.Type = type;
  397.    foc.Flags = flags;
  398.  
  399.    l = send((LONG)gd->gd_Socket, (UBYTE*)&foc, sizeof(foc), 0);
  400.  
  401.    return (BOOL)(l == sizeof(foc));
  402. }
  403. /*E*/
  404.  
  405. /*F*/ extern VOID main(VOID)
  406. {
  407.    int rc = RETURN_FAIL;
  408.    GD gd;
  409.  
  410.    if (gd = creategd())
  411.    {
  412.       d(("gd at %lx\n",gd))
  413.  
  414.       if (openall(gd))
  415.       {
  416.          GetProgramName(gd->gd_ProgramName, sizeof(gd->gd_ProgramName));
  417.  
  418.          if (parseargs(gd))
  419.          {
  420.             gd->gd_Socket = init_client(gd->gd_HostName, FO_SERVERNAME, FO_PROTOCOL, gd->gd_ProgramName);
  421.             if (gd->gd_Socket >= 0)
  422.             {
  423.                if (installhandler(gd))
  424.                {
  425.                   if (!gd->gd_Quiet)
  426.                      Printf( "Transparent mode on.\nEscape key is <Ctrl-Escape>.\n");
  427.  
  428.                   while(!(SetSignal(0,0) & SIGBREAKF_CTRL_C))
  429.                   {
  430.                      swait(&gd->gd_Full);
  431.                      if (request(gd, FOPT_Event, 0))
  432.                      {
  433.                         send((LONG)gd->gd_Socket, (UBYTE*)&gd->gd_Event[gd->gd_Read], sizeof(struct InputEvent), 0);
  434.                      }
  435.                      ssignal(&gd->gd_Empty);
  436.  
  437.                      gd->gd_Read = (gd->gd_Read+1) & (FIFO_COUNT-1);
  438.  
  439.                   }
  440.                   if (!gd->gd_Quiet)
  441.                      Printf( "Transparent mode left.\n");
  442.  
  443.                   removehandler(gd);
  444.                   rc = TRUE;
  445.                }
  446.  
  447.                if (!request(gd, FOPT_Finish, 0))
  448.                   Printf( "%s: could not finish connection\n", gd->gd_ProgramName);
  449.                else
  450.                   rc = RETURN_OK;
  451.             }
  452.             shutdown(gd->gd_Socket,2);
  453.             close(gd->gd_Socket);
  454.          }
  455.       }
  456.  
  457.       freeall(gd);
  458.    }
  459.  
  460.    exit(rc);
  461. }
  462. /*E*/
  463.  
  464.